/*     */ package com.zimbra.cs.mailbox;
/*     */ 
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.GuestAccount;
/*     */ import com.zimbra.cs.account.NamedEntry;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import java.security.SecureRandom;
/*     */ import java.util.Collections;
/*     */ import java.util.List;
/*     */ import java.util.concurrent.CopyOnWriteArrayList;
/*     */ import org.apache.commons.codec.binary.Hex;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class ACL
/*     */ {
/*     */   public static final short RIGHT_READ = 1;
/*     */   public static final short RIGHT_WRITE = 2;
/*     */   public static final short RIGHT_INSERT = 4;
/*     */   public static final short RIGHT_DELETE = 8;
/*     */   public static final short RIGHT_ACTION = 16;
/*     */   public static final short RIGHT_ADMIN = 256;
/*     */   public static final short RIGHT_SUBFOLDER = 512;
/*     */   public static final short RIGHT_PRIVATE = 1024;
/*     */   public static final short RIGHT_FREEBUSY = 2048;
/*     */   private static final short SUBFOLDER_RIGHTS = 5;
/*     */   private static final short GRANTABLE_RIGHTS = 3359;
/*     */   public static final byte GRANTEE_USER = 1;
/*     */   public static final byte GRANTEE_GROUP = 2;
/*     */   public static final byte GRANTEE_AUTHUSER = 3;
/*     */   public static final byte GRANTEE_DOMAIN = 4;
/*     */   public static final byte GRANTEE_COS = 5;
/*     */   public static final byte GRANTEE_PUBLIC = 6;
/*     */   public static final byte GRANTEE_GUEST = 7;
/*     */   public static final byte GRANTEE_KEY = 8;
/*     */   private static final int ACCESSKEY_SIZE_BYTES = 16;
/*     */   public ACL() {}
/*     */   
/*     */   public static class Grant
/*     */   {
/*     */     private String mGrantee;
/*     */     private String mName;
/*     */     private final byte mType;
/*     */     private short mRights;
/*     */     private String mSecret;
/* 104 */     private long mExpiry = 0L;
/*     */     private static final String FN_GRANTEE = "g";
/*     */     private static final String FN_NAME = "n";
/*     */     private static final String FN_TYPE = "t";
/*     */     private static final String FN_RIGHTS = "r";
/*     */     private static final String FN_PASSWORD = "a";
/*     */     private static final String FN_ACCESSKEY = "k";
/*     */     private static final String FN_EXPIRY = "e";
/*     */     
/*     */     Grant(String zimbraId, byte type, short rights)
/*     */     {
/* 115 */       this.mGrantee = zimbraId;
/* 116 */       this.mType = type;
/* 117 */       this.mRights = ((short)(rights & 0xD1F));
/*     */     }
/*     */     
/* 120 */     Grant(String zimbraId, byte type, short rights, String secret, long expiry) { this(zimbraId, type, rights);
/* 121 */       if ((this.mType == 7) || (this.mType == 8)) {
/* 122 */         this.mSecret = secret;
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */     public Grant(Metadata meta)
/*     */       throws ServiceException
/*     */     {
/* 131 */       this.mType = ((byte)(int)meta.getLong("t"));
/* 132 */       this.mRights = ((short)(int)(meta.getLong("r") & 0xD1F));
/* 133 */       this.mName = meta.get("n", null);
/* 134 */       if (hasGrantee())
/* 135 */         this.mGrantee = meta.get("g");
/* 136 */       if (this.mType == 7) {
/* 137 */         this.mSecret = meta.get("a", null);
/* 138 */       } else if (this.mType == 8)
/* 139 */         this.mSecret = meta.get("k");
/* 140 */       this.mExpiry = meta.getLong("e", 0L);
/*     */     }
/*     */     
/*     */ 
/* 144 */     public boolean hasGrantee() { return (this.mType != 3) && (this.mType != 6); }
/*     */     
/* 146 */     public String getGranteeId() { return hasGrantee() ? this.mGrantee : null; }
/*     */     
/* 148 */     public byte getGranteeType() { return this.mType; }
/*     */     
/* 150 */     public short getGrantedRights() { return this.mRights; }
/*     */     
/*     */ 
/*     */     public short getGrantedRights(Account acct, ACL acl)
/*     */       throws ServiceException
/*     */     {
/* 156 */       if (isExpired(acl)) {
/* 157 */         if (ZimbraLog.acl.isTraceEnabled()) {
/* 158 */           ZimbraLog.acl.trace("ACL.GrantedRights 0 for acl=%s (expired)", new Object[] { acl });
/*     */         }
/* 160 */         return 0;
/*     */       }
/* 162 */       if (matches(acct)) {
/* 163 */         if (ZimbraLog.acl.isTraceEnabled()) {
/* 164 */           ZimbraLog.acl.trace("ACL.GrantedRights %s for acl=%s", new Object[] { Short.valueOf(this.mRights), acl });
/*     */         }
/* 166 */         return this.mRights;
/*     */       }
/* 168 */       if (ZimbraLog.acl.isTraceEnabled()) {
/* 169 */         ZimbraLog.acl.trace("ACL.GrantedRights 0 for acl=%s (does not match %s)", new Object[] { acl, acct == null ? "'null acct'" : acct.getName() });
/*     */       }
/*     */       
/* 172 */       return 0;
/*     */     }
/*     */     
/*     */     private boolean isExpired(ACL acl) {
/* 176 */       long expiry = getEffectiveExpiry(acl);
/* 177 */       return (expiry != 0L) && (System.currentTimeMillis() > expiry);
/*     */     }
/*     */     
/*     */     public long getEffectiveExpiry(ACL acl) {
/* 181 */       long expiry = this.mExpiry;
/* 182 */       if (expiry == 0L) {
/* 183 */         if ((this.mType == 7) || (this.mType == 8)) {
/* 184 */           expiry = acl.getGuestGrantExpiry();
/* 185 */         } else if (this.mType != 6) {
/* 186 */           expiry = acl.getInternalGrantExpiry();
/*     */         }
/*     */       }
/* 189 */       return expiry;
/*     */     }
/*     */     
/*     */ 
/* 193 */     public String getGranteeName() { return this.mName; }
/*     */     
/* 195 */     public void setGranteeName(String name) { this.mName = name; }
/*     */     
/*     */ 
/*     */     public boolean matches(Account acct)
/*     */       throws ServiceException
/*     */     {
/* 201 */       Provisioning prov = Provisioning.getInstance();
/* 202 */       if (acct == null)
/* 203 */         return this.mType == 6;
/* 204 */       switch (this.mType) {
/* 205 */       case 6:  return true;
/* 206 */       case 3:  return isInternalAccount(acct);
/* 207 */       case 5:  return this.mGrantee.equals(getId(prov.getCOS(acct)));
/* 208 */       case 4:  return matchesDomainGrantee(acct, prov);
/* 209 */       case 2:  return prov.inACLGroup(acct, this.mGrantee);
/* 210 */       case 1:  return this.mGrantee.equals(acct.getId());
/* 211 */       case 7:  return matchesGuestAccount(acct);
/* 212 */       case 8:  return matchesAccessKey(acct); }
/* 213 */       throw ServiceException.FAILURE("unknown ACL grantee type: " + this.mType, null);
/*     */     }
/*     */     
/*     */     private boolean matchesDomainGrantee(Account acct, Provisioning prov) throws ServiceException
/*     */     {
/* 218 */       return (!acct.isIsExternalVirtualAccount()) && (this.mGrantee.equals(getId(prov.getDomain(acct))));
/*     */     }
/*     */     
/*     */     private boolean isInternalAccount(Account acct) {
/* 222 */       return (!acct.getId().equals("99999999-9999-9999-9999-999999999999")) && (!acct.isIsExternalVirtualAccount());
/*     */     }
/*     */     
/*     */     private boolean matchesGuestAccount(Account acct) {
/* 226 */       if ((acct instanceof GuestAccount))
/*     */       {
/*     */ 
/* 229 */         if (!StringUtil.isNullOrEmpty(this.mSecret)) {
/* 230 */           return ((GuestAccount)acct).matches(this.mGrantee, this.mSecret);
/*     */         }
/* 232 */       } else if (acct.isIsExternalVirtualAccount()) {
/* 233 */         return this.mGrantee.equalsIgnoreCase(acct.getExternalUserMailAddress());
/*     */       }
/* 235 */       return false;
/*     */     }
/*     */     
/*     */     private boolean matchesAccessKey(Account acct) {
/* 239 */       if (!(acct instanceof GuestAccount))
/* 240 */         return false;
/* 241 */       return ((GuestAccount)acct).matchesAccessKey(this.mGrantee, this.mSecret);
/*     */     }
/*     */     
/*     */ 
/*     */     private static final String getId(NamedEntry entry)
/*     */     {
/* 247 */       return entry == null ? null : entry.getId();
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     public boolean isGrantee(String zimbraId)
/*     */     {
/* 258 */       if ((zimbraId == null) || (zimbraId.equals("99999999-9999-9999-9999-999999999999")))
/* 259 */         return this.mType == 6;
/* 260 */       if (zimbraId.equals("00000000-0000-0000-0000-000000000000"))
/* 261 */         return this.mType == 3;
/* 262 */       return (this.mType == 7) || (this.mType == 8) ? zimbraId.equalsIgnoreCase(this.mGrantee) : zimbraId.equals(this.mGrantee);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     void setRights(short rights)
/*     */     {
/* 273 */       this.mRights = rights;
/*     */     }
/*     */     
/*     */ 
/*     */     void setPassword(String password)
/*     */     {
/* 279 */       if (((this.mType == 7) || (this.mType == 8)) && (password != null)) {
/* 280 */         this.mSecret = password;
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */     public String getPassword()
/*     */     {
/* 287 */       return this.mSecret;
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */     public void setExpiry(long expiry)
/*     */     {
/* 295 */       this.mExpiry = expiry;
/*     */     }
/*     */     
/*     */     public long getExpiry() {
/* 299 */       return this.mExpiry;
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     public Metadata encode()
/*     */     {
/* 314 */       Metadata meta = new Metadata();
/* 315 */       meta.put("g", hasGrantee() ? this.mGrantee : null);
/* 316 */       meta.put("n", this.mName);
/* 317 */       meta.put("t", this.mType);
/*     */       
/* 319 */       meta.put("r", this.mRights);
/*     */       
/* 321 */       if (this.mType == 8) {
/* 322 */         meta.put("k", this.mSecret);
/*     */       } else
/* 324 */         meta.put("a", this.mSecret);
/* 325 */       meta.put("e", this.mExpiry);
/*     */       
/* 327 */       return meta;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/* 332 */   private final List<Grant> mGrants = new CopyOnWriteArrayList();
/*     */   
/* 334 */   private long mInternalGrantExpiry = 0L;
/*     */   
/* 336 */   private long mGuestGrantExpiry = 0L;
/*     */   private static final String FN_GRANTS = "g";
/*     */   private static final String FN_INT_GRANT_EXPIRY = "ie";
/*     */   private static final String FN_GST_GRANT_EXPIRY = "ge";
/*     */   
/* 341 */   public ACL(long internalGrantExpiry, long guestGrantExpiry) { this.mInternalGrantExpiry = internalGrantExpiry;
/* 342 */     this.mGuestGrantExpiry = guestGrantExpiry;
/*     */   }
/*     */   
/*     */   public ACL(MetadataList mlist) {
/* 346 */     decodeGrants(mlist);
/*     */   }
/*     */   
/*     */   public ACL(Metadata meta) {
/* 350 */     MetadataList mlist = null;
/*     */     try {
/* 352 */       mlist = meta.getList("g", true);
/* 353 */       this.mInternalGrantExpiry = meta.getLong("ie", 0L);
/* 354 */       this.mGuestGrantExpiry = meta.getLong("ge", 0L);
/*     */     } catch (ServiceException e) {
/* 356 */       ZimbraLog.mailbox.warn("malformed ACL: " + meta, e);
/*     */     }
/* 358 */     if (mlist != null) {
/* 359 */       decodeGrants(mlist);
/*     */     }
/*     */   }
/*     */   
/*     */   private void decodeGrants(MetadataList mlist) {
/* 364 */     for (int i = 0; i < mlist.size(); i++) {
/*     */       try {
/* 366 */         this.mGrants.add(new Grant(mlist.getMap(i)));
/*     */       } catch (ServiceException e) {
/* 368 */         ZimbraLog.mailbox.warn("malformed permission grant: " + mlist, e);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public long getInternalGrantExpiry() {
/* 374 */     return this.mInternalGrantExpiry;
/*     */   }
/*     */   
/*     */   public long getGuestGrantExpiry() {
/* 378 */     return this.mGuestGrantExpiry;
/*     */   }
/*     */   
/*     */ 
/*     */   public static final char ABBR_READ = 'r';
/*     */   
/*     */   public static final char ABBR_WRITE = 'w';
/*     */   
/*     */   public static final char ABBR_INSERT = 'i';
/*     */   public Short getGrantedRights(Account authuser)
/*     */     throws ServiceException
/*     */   {
/* 390 */     if (this.mGrants.isEmpty()) {
/* 391 */       if (ZimbraLog.acl.isTraceEnabled()) {
/* 392 */         ZimbraLog.acl.trace("ACL.GrantedRights NULL (no grants)");
/*     */       }
/* 394 */       return null;
/*     */     }
/*     */     
/* 397 */     short rightsGranted = 0;
/* 398 */     for (Grant grant : this.mGrants) {
/* 399 */       rightsGranted = (short)(rightsGranted | grant.getGrantedRights(authuser, this));
/*     */     }
/* 401 */     if ((rightsGranted & 0x5) == 5) {
/* 402 */       rightsGranted = (short)(rightsGranted | 0x200);
/*     */     }
/* 404 */     if (ZimbraLog.acl.isTraceEnabled()) {
/* 405 */       ZimbraLog.acl.trace("ACL.GrantedRights %s from %s grants", new Object[] { Short.valueOf(rightsGranted), Integer.valueOf(this.mGrants.size()) });
/*     */     }
/* 407 */     return Short.valueOf(rightsGranted);
/*     */   }
/*     */   
/*     */   public boolean isEmpty()
/*     */   {
/* 412 */     return this.mGrants.isEmpty();
/*     */   }
/*     */   
/*     */   public Grant grantAccess(String zimbraId, byte type, short rights, String secret) throws ServiceException
/*     */   {
/* 417 */     return grantAccess(zimbraId, type, rights, secret, 0L);
/*     */   }
/*     */   
/*     */ 
/*     */   public static final char ABBR_DELETE = 'd';
/*     */   
/*     */   public static final char ABBR_ACTION = 'x';
/*     */   
/*     */   public static final char ABBR_ADMIN = 'a';
/*     */   
/*     */   public static final char ABBR_PRIVATE = 'p';
/*     */   
/*     */   public static final char ABBR_FREEBUSY = 'f';
/*     */   public static final char ABBR_CREATE_FOLDER = 'c';
/*     */   public Grant grantAccess(String zimbraId, byte type, short rights, String secret, long expiry)
/*     */     throws ServiceException
/*     */   {
/* 434 */     if (expiry != 0L) {
/* 435 */       if ((type == 7) || (type == 8)) {
/* 436 */         if ((this.mGuestGrantExpiry != 0L) && (expiry > this.mGuestGrantExpiry)) {
/* 437 */           throw ServiceException.PERM_DENIED("share expiration policy conflict");
/*     */         }
/* 439 */       } else if (type != 6)
/*     */       {
/* 441 */         if ((this.mInternalGrantExpiry != 0L) && (expiry > this.mInternalGrantExpiry)) {
/* 442 */           throw ServiceException.PERM_DENIED("share expiration policy conflict");
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 447 */     if (type == 3) {
/* 448 */       zimbraId = "00000000-0000-0000-0000-000000000000";
/* 449 */     } else if (type == 6) {
/* 450 */       zimbraId = "99999999-9999-9999-9999-999999999999";
/* 451 */     } else if (zimbraId == null) {
/* 452 */       throw ServiceException.INVALID_REQUEST("missing grantee id", null);
/*     */     }
/*     */     
/* 455 */     if ((type == 8) && (secret == null)) {
/* 456 */       secret = generateAccessKey();
/*     */     }
/* 458 */     if (!this.mGrants.isEmpty()) {
/* 459 */       for (Grant grant : this.mGrants) {
/* 460 */         if (grant.isGrantee(zimbraId)) {
/* 461 */           if ((grant.getGrantedRights() == rights) && (((type != 7) && (type != 8)) || ((StringUtil.equal(grant.getPassword(), secret)) && (grant.getExpiry() == expiry))))
/*     */           {
/*     */ 
/*     */ 
/*     */ 
/* 466 */             throw MailServiceException.GRANTEE_EXISTS(zimbraId, null);
/*     */           }
/*     */           
/* 469 */           grant.setRights(rights);
/* 470 */           if ((type == 7) || (type == 8))
/* 471 */             grant.setPassword(secret);
/* 472 */           grant.setExpiry(expiry);
/* 473 */           return grant;
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 478 */     Grant grant = new Grant(zimbraId, type, rights, secret, expiry);
/* 479 */     this.mGrants.add(grant);
/* 480 */     return grant;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public boolean revokeAccess(String zimbraId)
/*     */   {
/* 490 */     if ((this.mGrants == null) || (this.mGrants.isEmpty()))
/* 491 */       return false;
/* 492 */     int count = this.mGrants.size();
/* 493 */     for (Grant grant : this.mGrants) {
/* 494 */       if (grant.isGrantee(zimbraId)) {
/* 495 */         this.mGrants.remove(grant);
/*     */       }
/*     */     }
/* 498 */     return this.mGrants.size() != count;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public Metadata encode()
/*     */   {
/* 506 */     Metadata meta = new Metadata();
/* 507 */     MetadataList mlist = new MetadataList();
/* 508 */     for (Grant grant : this.mGrants)
/* 509 */       mlist.add(grant.encode());
/* 510 */     meta.put("g", mlist);
/* 511 */     meta.put("ie", this.mInternalGrantExpiry);
/* 512 */     meta.put("ge", this.mGuestGrantExpiry);
/* 513 */     return meta;
/*     */   }
/*     */   
/*     */   public String toString() {
/* 517 */     return encode().toString();
/*     */   }
/*     */   
/*     */   public ACL duplicate() {
/* 521 */     return new ACL(encode());
/*     */   }
/*     */   
/*     */   public List<Grant> getGrants()
/*     */   {
/* 526 */     return Collections.unmodifiableList(this.mGrants);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static short stringToRights(String encoded)
/*     */     throws ServiceException
/*     */   {
/* 540 */     short rights = 0;
/* 541 */     if ((encoded != null) && (encoded.length() != 0)) {
/* 542 */       for (int i = 0; i < encoded.length(); i++) {
/* 543 */         switch (encoded.charAt(i)) {
/* 544 */         case 'r':  rights = (short)(rights | 0x1); break;
/* 545 */         case 'w':  rights = (short)(rights | 0x2); break;
/* 546 */         case 'i':  rights = (short)(rights | 0x4); break;
/* 547 */         case 'd':  rights = (short)(rights | 0x8); break;
/* 548 */         case 'x':  rights = (short)(rights | 0x10); break;
/* 549 */         case 'a':  rights = (short)(rights | 0x100); break;
/* 550 */         case 'p':  rights = (short)(rights | 0x400); break;
/* 551 */         case 'f':  rights = (short)(rights | 0x800); break;
/*     */         case 'c': 
/*     */           break; case 'b': case 'e': case 'g': case 'h': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'q': case 's': case 't': case 'u': case 'v': default:  throw ServiceException.INVALID_REQUEST("unknown right: " + encoded.charAt(i), null);
/*     */         }
/*     */       }
/*     */     }
/* 557 */     return rights;
/*     */   }
/*     */   
/*     */   public static String rightsToString(short rights) {
/* 561 */     if (rights == 0)
/* 562 */       return "";
/* 563 */     StringBuffer sb = new StringBuffer();
/* 564 */     if ((rights & 0x1) != 0) sb.append('r');
/* 565 */     if ((rights & 0x2) != 0) sb.append('w');
/* 566 */     if ((rights & 0x4) != 0) sb.append('i');
/* 567 */     if ((rights & 0x8) != 0) sb.append('d');
/* 568 */     if ((rights & 0x10) != 0) sb.append('x');
/* 569 */     if ((rights & 0x100) != 0) sb.append('a');
/* 570 */     if ((rights & 0x400) != 0) sb.append('p');
/* 571 */     if ((rights & 0x800) != 0) sb.append('f');
/* 572 */     if ((rights & 0x200) != 0) sb.append('c');
/* 573 */     return sb.toString();
/*     */   }
/*     */   
/*     */   public static byte stringToType(String typeStr) throws ServiceException {
/* 577 */     if (typeStr.equalsIgnoreCase("usr")) return 1;
/* 578 */     if (typeStr.equalsIgnoreCase("grp")) return 2;
/* 579 */     if (typeStr.equalsIgnoreCase("cos")) return 5;
/* 580 */     if (typeStr.equalsIgnoreCase("dom")) return 4;
/* 581 */     if (typeStr.equalsIgnoreCase("all")) return 3;
/* 582 */     if (typeStr.equalsIgnoreCase("pub")) return 6;
/* 583 */     if (typeStr.equalsIgnoreCase("guest")) return 7;
/* 584 */     if (typeStr.equalsIgnoreCase("key")) return 8;
/* 585 */     throw ServiceException.INVALID_REQUEST("unknown grantee type: " + typeStr, null);
/*     */   }
/*     */   
/*     */   public static String typeToString(byte type) {
/* 589 */     if (type == 1) return "usr";
/* 590 */     if (type == 2) return "grp";
/* 591 */     if (type == 6) return "pub";
/* 592 */     if (type == 3) return "all";
/* 593 */     if (type == 5) return "cos";
/* 594 */     if (type == 4) return "dom";
/* 595 */     if (type == 7) return "guest";
/* 596 */     if (type == 8) return "key";
/* 597 */     return null;
/*     */   }
/*     */   
/*     */   public static String generateAccessKey() {
/* 601 */     SecureRandom random = new SecureRandom();
/* 602 */     byte[] key = new byte[16];
/* 603 */     random.nextBytes(key);
/*     */     
/*     */ 
/* 606 */     return new String(Hex.encodeHex(key));
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailbox/ACL.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */